(* q1 *)
let rec concat1 l = 
  match l with
    [] -> []
  | h :: tl -> h @ concat1 tl

let concat2 l = 
  let rec helper acc l =
    match l with
      [] -> acc
    | h :: tl -> helper (acc @ h) tl
  in
  helper [] l

(* q2 *)
let mem_true l = 
  List.(for_all (fun i -> mem true i) l)

(* q3 *)
let count_exclamation s = 
  String.fold_left (fun acc c -> 
    if c = '!' then acc + 1
    else acc
  ) 0 s

(* q4 *)
let replace_exclamation = String.map (fun c -> if c = '!' then '.' else c)

(* q5 *)
let concat_string l = 
  String.concat "" l

(* q6 *)
let concat_string2 l = 
  let b = Buffer.create 10 in
  List.iter (fun i -> Buffer.add_string b i) l ;
  Buffer.contents b

(* q7 *)
let sub_string s = 
  let count = ref 0 in
  let ocaml = "OCaml" in
  let size = String.length ocaml in
  for i = 0 to String.length s - size do
    let sub_s = String.sub s i size in
    if sub_s = ocaml then count := !count + 1
  done ;
  !count